package org.apache.shiro.session.mgt;

import java.io.Serializable;
import java.sql.Date;
import java.util.List;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.CachingSessionDAO;
import org.kl.bf.entity.basic.Sessions;
import org.kl.bf.repository.basic.SessionsDao;
import org.kl.bf.utils.UUIDGenerator;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.StringUtils;

/**
 * 
 * @Author hqm
 * @CreateTime 2014年6月17日 下午9:27:43
 */
public class KLSessionDao extends CachingSessionDAO {

	private SessionsDao sessionsDao;
	private JdbcTemplate jdbcTemplate;
	/**
	 * 上次同步数据库的时间戳
	 */
	private static final String LAST_SYNC_DB_TIMESTAMP = KLSessionDao.class.getName() + "LAST_SYNC_DB_TIMESTAMP";
	/**
	 * 同步session到数据库的周期 单位为毫秒（默认5分钟）
	 */
	private long dbSyncPeriod = 5 * 60 * 1000;

	@Override
	protected Serializable doCreate(Session session) {
		Serializable sessionId = generateSessionId(session);
		assignSessionId(session, sessionId);
		if (session != null && session instanceof OnlineSession) {
			OnlineSession s = (OnlineSession) session;
			String sql = "INSERT INTO basic_sessions(id,user_id,session_id,host,user_agent,system_host,start_time,last_access_time,online_status,session_serialize) VALUES ( ?,?,?,?,?,?,?,?,?,?)";
			jdbcTemplate.update(sql, UUIDGenerator.getUUID(), null, sessionId, s.getHost(), s.getUserAgent(), s.getSystemHost(), new Date(s
					.getStartTimestamp().getTime()), new Date(s.getLastAccessTime().getTime()), s.getStatus().getInfo(), SerializableUtils
					.serialize(session));
		}
		return sessionId;
	}

	@Override
	protected void doUpdate(Session session) {
		if (session instanceof ValidatingSession && !((ValidatingSession) session).isValid()) {
			return; // 如果会话过期/停止 没必要再更新了
		}
		if (session != null && session instanceof OnlineSession) {
			OnlineSession s = (OnlineSession) session;
			Date lastSyncTimestamp = (Date) session.getAttribute(LAST_SYNC_DB_TIMESTAMP);

			// 当会话中的属性改变时-->强制同步
			// 如果对于属性丢失影响不大 可以考虑把这块功能去掉
			if (lastSyncTimestamp != null) {
				boolean needSync = true;
				long deltaTime = session.getLastAccessTime().getTime() - lastSyncTimestamp.getTime();
				if (deltaTime < dbSyncPeriod) { // 时间差不足 无需同步
					needSync = false;
				}
				boolean isGuest = s.getUser() == null || StringUtils.isEmpty(s.getUser().getId());

				// 如果不是游客 且session 数据变更了 同步
				if (isGuest == false) {
					needSync = true;
				}

				if (needSync == false) {
					return;
				}
			}

			session.setAttribute(LAST_SYNC_DB_TIMESTAMP, new Date(session.getLastAccessTime().getTime()));
			String sql = "update basic_sessions set session_serialize=?, user_id=? where session_id=?";
			jdbcTemplate.update(sql, SerializableUtils.serialize(session), s.getUser().getId(), session.getId());
		}
	}

	@Override
	protected void doDelete(Session session) {
		String sql = "delete from basic_sessions where session_id=?";
		jdbcTemplate.update(sql, session.getId());
	}

	@Override
	protected Session doReadSession(Serializable sessionId) {
		List<Sessions> sessionsList = sessionsDao.findBySessionId((String) sessionId);
		if (sessionsList.size() == 0)
			return null;
		return SerializableUtils.deserialize(sessionsList.get(0).getSessionSerialize());
	}

	public void setSessionsDao(SessionsDao sessionsDao) {
		this.sessionsDao = sessionsDao;
	}

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

}
